import pandas as pd
import pymysql
from sqlalchemy import create_engine
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.oxml import parse_xml
import os
from datetime import datetime
import json

# 数据库配置（请修改为你的配置）
DB_CONFIG = {
    "host": "localhost",
    "port": 3306,
    "user": "root",
    "password": "",  # 替换为你的密码
    "db": "stock_db",
    "charset": "utf8mb4"
}


def create_database_connection():
    """创建数据库连接"""
    try:
        engine = create_engine(
            f"mysql+pymysql://{DB_CONFIG['user']}:{DB_CONFIG['password']}@{DB_CONFIG['host']}:{DB_CONFIG['port']}/{DB_CONFIG['db']}?charset={DB_CONFIG['charset']}"
        )
        return engine
    except Exception as e:
        print(f"数据库连接失败: {str(e)}")
        raise


def read_company_detail_data(engine, limit=None):
    """从company_detail_analysis表读取公司数据"""
    try:
        query = """
               SELECT 
            id AS '主键ID',
            stock_code AS '股票代码',
			(select name from a_stock_basic_info m where m.`code`=stock_code) 上市公司名称,
            establishment_date AS '成立日期',
            manager AS '管理者',
            manager_introduction AS '管理者介绍',
            registered_address AS '注册地址',
            company_type AS '公司性质',
            primary_industry AS '一级行业',
            secondary_industry AS '二级行业',
            tertiary_industry AS '三级行业',
            business_scope AS '经营范围',
            main_business AS '主营业务',
            violation_time AS '违规时间',
            violation_type AS '违规性质',
            violation_description AS '违规描述',
            listing_date AS '上市时间',
            controlling_shareholder AS '控股股东',
            business_development_analysis AS '业务发展分析',
            financial_condition_analysis AS '财务状况分析',
            profit_model AS '盈利模式',
            moat AS '护城河',
            customer_group AS '客户群体',
            competitors AS '竞争对手',
            business_area AS '业务区域',
            subsidiaries AS '子企业',
            core_products_services AS '核心产品或服务',
            related_upstream_downstream_listed_companies AS '关联上下游上市企业',
            main_factors_affecting_operation AS '经营状况主要影响因素',
            former_names AS '企业曾用名',
            csrc_warning_letters AS '被证监会发过警告函情况',
            major_shareholder_reduction AS '大股东减持情况',
            company_goodwill AS '公司商誉',
            goodwill_scale AS '商誉规模',
            asset_provision_information AS '资产计提信息',
            position_in_subdivision_industry AS '细分行业中地位',
            debt_ratio_5years AS '近5年的负债率',
            revenue_5years AS '近5年的营业收入',
            deducted_net_profit_5years AS '近5年的扣费净利润',
            gross_profit_margin_5years AS '近5年的毛利率',
            same_industry_market_value_ranking AS '同行业市值排名公司',
            dominant_products_services_in_market AS '市场中占主导地位的产品服务',
            company_highlights AS '公司亮点',
            company_risk_points AS '公司风险点',
            themes_concepts AS '题材/概念',
            what_company_does AS '公司干什么的',
            major_customers AS '主要客户',
            stock_price_surge_periods AS '股票大涨时间段',
            performance_indicators_during_surge AS '股票大涨时间段内业绩指标详细描述',
            is_cyclical AS '是否为周期股',
            stock_price_characteristics AS '此公司的股价变动特点',
            analysis_time AS '分析时间',
            batch_id AS '批次ID',
            created_at AS '创建时间'
        FROM company_detail_analysis
        """
        if limit:
            query += f" LIMIT {limit}"

        df = pd.read_sql(query, engine)
        print(f"成功读取 {len(df)} 条公司详细数据")
        return df
    except Exception as e:
        print(f"读取数据失败: {str(e)}")
        raise


def set_chinese_font(run, font_name='微软雅黑'):
    """设置中文字体"""
    run.font.name = font_name
    run._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)


def add_company_header(doc, company_data):
    """添加公司头部信息"""
    # 主标题
    title = doc.add_heading('', level=0)
    title_run = title.add_run(f"{company_data['上市公司名称']}（{company_data['股票代码']}）投资分析报告")
    title_run.font.size = Pt(18)
    title_run.bold = True
    title_run.font.color.rgb = RGBColor(0, 0, 128)  # 深蓝色
    set_chinese_font(title_run)
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER

    doc.add_paragraph()  # 空行

    # 基本信息表格
    table = doc.add_table(rows=6, cols=2)
    table.style = 'Light Grid Accent 1'

    # 设置表格基本信息
    info_data = [
        ('公司名称', company_data['上市公司名称']),
        ('股票代码', company_data['股票代码']),
        ('成立日期', company_data['成立日期'] if pd.notna(company_data['成立日期']) and str(
            company_data['成立日期']) != '暂无信息' else '暂无'),
        ('上市时间', company_data['上市时间'] if pd.notna(company_data['上市时间']) and str(
            company_data['上市时间']) != '暂无信息' else '暂无'),
        ('公司性质', company_data['公司性质'] if pd.notna(company_data['公司性质']) and str(
            company_data['公司性质']) != '暂无信息' else '暂无'),
        ('注册地址', company_data['注册地址'] if pd.notna(company_data['注册地址']) and str(
            company_data['注册地址']) != '暂无信息' else '暂无')
    ]

    for i, (label, value) in enumerate(info_data):
        row_cells = table.rows[i].cells
        row_cells[0].text = label
        row_cells[1].text = str(value)

        # 设置字体
        for cell in row_cells:
            for paragraph in cell.paragraphs:
                for run in paragraph.runs:
                    set_chinese_font(run)
                    if cell == row_cells[0]:  # 标签单元格加粗
                        run.bold = True

    doc.add_paragraph()  # 空行


def add_company_overview(doc, company_data):
    """添加公司概况"""
    doc.add_heading('一、公司概况', level=1)

    # 公司基本信息
    overview_info = [
        ('一级行业', company_data['一级行业']),
        ('二级行业', company_data['二级行业']),
        ('三级行业', company_data['三级行业']),
        ('控股股东', company_data['控股股东']),
        ('企业曾用名', company_data['企业曾用名']),
        ('公司干什么的', company_data['公司干什么的'])
    ]

    for label, value in overview_info:
        if pd.notna(value) and str(value).strip() and str(value) != '暂无信息' and str(value) != 'None':
            p = doc.add_paragraph()
            p.add_run(f"{label}：").bold = True
            p.add_run(str(value))
            set_chinese_font(p.runs[0])
            set_chinese_font(p.runs[1])

    doc.add_paragraph()  # 空行


def add_business_analysis(doc, company_data):
    """添加业务分析"""
    doc.add_heading('二、业务分析', level=1)

    # 经营范围
    if pd.notna(company_data['经营范围']) and str(company_data['经营范围']).strip() and str(
            company_data['经营范围']) != '暂无信息':
        doc.add_heading('经营范围', level=2)
        p = doc.add_paragraph(str(company_data['经营范围']))
        set_chinese_font(p.runs[0])

    # 主营业务
    if pd.notna(company_data['主营业务']) and str(company_data['主营业务']).strip() and str(
            company_data['主营业务']) != '暂无信息':
        doc.add_heading('主营业务', level=2)
        p = doc.add_paragraph(str(company_data['主营业务']))
        set_chinese_font(p.runs[0])

    # 核心产品或服务
    if pd.notna(company_data['核心产品或服务']) and str(company_data['核心产品或服务']).strip() and str(
            company_data['核心产品或服务']) != '暂无信息':
        doc.add_heading('核心产品或服务', level=2)
        p = doc.add_paragraph(str(company_data['核心产品或服务']))
        set_chinese_font(p.runs[0])

    # 市场中占主导地位的产品/服务
    if pd.notna(company_data['市场中占主导地位的产品服务']) and str(
            company_data['市场中占主导地位的产品服务']).strip() and str(
            company_data['市场中占主导地位的产品服务']) != '暂无信息':
        doc.add_heading('主导产品/服务', level=2)
        p = doc.add_paragraph(str(company_data['市场中占主导地位的产品服务']))
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_market_analysis(doc, company_data):
    """添加市场分析"""
    doc.add_heading('三、市场分析', level=1)

    analysis_items = [
        ('客户群体', company_data['客户群体']),
        ('主要客户', company_data['主要客户']),
        ('业务区域', company_data['业务区域']),
        ('盈利模式', company_data['盈利模式']),
        ('护城河', company_data['护城河']),
        ('细分行业中地位', company_data['细分行业中地位'])
    ]

    for label, value in analysis_items:
        if pd.notna(value) and str(value).strip() and str(value) != '暂无信息' and str(value) != 'None':
            doc.add_heading(label, level=2)
            p = doc.add_paragraph(str(value))
            set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_competitive_analysis(doc, company_data):
    """添加竞争分析"""
    doc.add_heading('四、竞争分析', level=1)

    # 竞争对手
    if pd.notna(company_data['竞争对手']) and str(company_data['竞争对手']).strip() and str(
            company_data['竞争对手']) != '暂无信息':
        doc.add_heading('竞争对手', level=2)
        p = doc.add_paragraph(str(company_data['竞争对手']))
        set_chinese_font(p.runs[0])

    # 同行业市值排名公司
    if pd.notna(company_data['同行业市值排名公司']) and str(company_data['同行业市值排名公司']).strip() and str(
            company_data['同行业市值排名公司']) != '暂无信息':
        doc.add_heading('同行业公司对比', level=2)
        p = doc.add_paragraph(str(company_data['同行业市值排名公司']))
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_financial_analysis(doc, company_data):
    """添加财务分析"""
    doc.add_heading('五、财务分析', level=1)

    # 财务状况分析
    if pd.notna(company_data['财务状况分析']) and str(company_data['财务状况分析']).strip() and str(
            company_data['财务状况分析']) != '暂无信息':
        doc.add_heading('财务状况分析', level=2)
        p = doc.add_paragraph(str(company_data['财务状况分析']))
        set_chinese_font(p.runs[0])

    # 财务指标数据
    financial_metrics = [
        ('近5年负债率', company_data['近5年的负债率']),
        ('近5年营业收入', company_data['近5年的营业收入']),
        ('近5年扣非净利润', company_data['近5年的扣费净利润']),
        ('近5年毛利率', company_data['近5年的毛利率'])
    ]

    for label, value in financial_metrics:
        if pd.notna(value) and str(value).strip() and str(value) != '暂无信息':
            doc.add_heading(label, level=2)
            try:
                # 尝试解析JSON格式的财务数据
                financial_data = json.loads(value)
                if isinstance(financial_data, dict):
                    for year, metric_value in financial_data.items():
                        p = doc.add_paragraph(f"{year}: {metric_value}")
                        set_chinese_font(p.runs[0])
                else:
                    p = doc.add_paragraph(str(value))
                    set_chinese_font(p.runs[0])
            except:
                p = doc.add_paragraph(str(value))
                set_chinese_font(p.runs[0])

    # 商誉信息
    if pd.notna(company_data['公司商誉']) and str(company_data['公司商誉']).strip() and str(
            company_data['公司商誉']) != '暂无信息':
        doc.add_heading('公司商誉', level=2)
        goodwill_scale = company_data['商誉规模'] if pd.notna(company_data['商誉规模']) and str(
            company_data['商誉规模']) != '暂无信息' else '未知'
        p = doc.add_paragraph(f"{company_data['公司商誉']}（规模：{goodwill_scale}）")
        set_chinese_font(p.runs[0])

    # 资产计提信息
    if pd.notna(company_data['资产计提信息']) and str(company_data['资产计提信息']).strip() and str(
            company_data['资产计提信息']) != '暂无信息':
        doc.add_heading('资产计提信息', level=2)
        p = doc.add_paragraph(str(company_data['资产计提信息']))
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_development_analysis(doc, company_data):
    """添加发展分析"""
    doc.add_heading('六、业务发展分析', level=1)

    # 业务发展分析
    if pd.notna(company_data['业务发展分析']) and str(company_data['业务发展分析']).strip() and str(
            company_data['业务发展分析']) != '暂无信息':
        p = doc.add_paragraph(str(company_data['业务发展分析']))
        set_chinese_font(p.runs[0])

    # 公司亮点
    if pd.notna(company_data['公司亮点']) and str(company_data['公司亮点']).strip() and str(
            company_data['公司亮点']) != '暂无信息':
        doc.add_heading('公司亮点', level=2)
        p = doc.add_paragraph(str(company_data['公司亮点']))
        set_chinese_font(p.runs[0])

    # 题材/概念
    if pd.notna(company_data['题材/概念']) and str(company_data['题材/概念']).strip() and str(
            company_data['题材/概念']) != '暂无信息':
        doc.add_heading('题材概念', level=2)
        p = doc.add_paragraph(str(company_data['题材/概念']))
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_risk_analysis(doc, company_data):
    """添加风险分析"""
    doc.add_heading('七、风险分析', level=1)

    risk_items = [
        ('经营状况主要影响因素', company_data['经营状况主要影响因素']),
        ('公司风险点', company_data['公司风险点']),
        ('违规情况', f"{company_data['违规时间']} - {company_data['违规性质']}: {company_data['违规描述']}"
        if pd.notna(company_data['违规时间']) and str(company_data['违规时间']).strip() and str(
            company_data['违规时间']) != '暂无信息' else None),
        ('证监会警告函', company_data['被证监会发过警告函情况']),
        ('大股东减持', company_data['大股东减持情况']),
        ('是否为周期股', company_data['是否为周期股'])
    ]

    has_risk_data = False
    for label, value in risk_items:
        if value and pd.notna(value) and str(value).strip() and str(value) != '暂无信息' and str(value) != 'None':
            has_risk_data = True
            p = doc.add_paragraph(style='List Bullet')
            p.add_run(f"{label}：").bold = True
            p.add_run(str(value))
            set_chinese_font(p.runs[0])
            set_chinese_font(p.runs[1])

    if not has_risk_data:
        p = doc.add_paragraph('暂无重大风险事件记录')
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_corporate_structure(doc, company_data):
    """添加公司结构"""
    doc.add_heading('八、公司结构', level=1)

    structure_items = [
        ('子企业', company_data['子企业']),
        ('关联上下游上市企业', company_data['关联上下游上市企业'])
    ]

    has_structure_data = False
    for label, value in structure_items:
        if pd.notna(value) and str(value).strip() and str(value) != '暂无信息' and str(value) != 'None':
            has_structure_data = True
            doc.add_heading(label, level=2)
            p = doc.add_paragraph(str(value))
            set_chinese_font(p.runs[0])

    if not has_structure_data:
        p = doc.add_paragraph('暂无公司结构信息')
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_management_info(doc, company_data):
    """添加管理层信息"""
    if pd.notna(company_data['管理者']) and str(company_data['管理者']).strip() and str(
            company_data['管理者']) != '暂无信息':
        doc.add_heading('九、管理层信息', level=1)

        p = doc.add_paragraph()
        p.add_run('管理者：').bold = True
        p.add_run(str(company_data['管理者']))
        set_chinese_font(p.runs[0])
        set_chinese_font(p.runs[1])

        if pd.notna(company_data['管理者介绍']) and str(company_data['管理者介绍']).strip() and str(
                company_data['管理者介绍']) != '暂无信息':
            doc.add_heading('管理者介绍', level=2)
            p = doc.add_paragraph(str(company_data['管理者介绍']))
            set_chinese_font(p.runs[0])

        doc.add_paragraph()  # 空行


def add_stock_analysis(doc, company_data):
    """添加股票表现分析"""
    doc.add_heading('十、股票表现分析', level=1)

    stock_items = [
        ('股票大涨时间段', company_data['股票大涨时间段']),
        ('大涨期间业绩表现', company_data['股票大涨时间段内业绩指标详细描述']),
        ('股价变动特点', company_data['此公司的股价变动特点']),
        ('是否为周期股', company_data['是否为周期股'])
    ]

    has_stock_data = False
    for label, value in stock_items:
        if pd.notna(value) and str(value).strip() and str(value) != '暂无信息' and str(value) != 'None':
            has_stock_data = True
            p = doc.add_paragraph()
            p.add_run(f"{label}：").bold = True
            p.add_run(str(value))
            set_chinese_font(p.runs[0])
            set_chinese_font(p.runs[1])

    if not has_stock_data:
        p = doc.add_paragraph('暂无股票表现分析数据')
        set_chinese_font(p.runs[0])

    doc.add_paragraph()  # 空行


def add_report_footer(doc):
    """添加报告页脚"""
    doc.add_paragraph()  # 空行
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    run = p.add_run(f"报告生成时间：{datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')}")
    run.italic = True
    run.font.color.rgb = RGBColor(128, 128, 128)  # 灰色
    set_chinese_font(run)


def generate_company_report(company_data, output_dir='company_reports'):
    """为单个公司生成Word报告"""
    try:
        # 创建输出目录
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        # 创建文档
        doc = Document()

        # 设置文档基本样式
        style = doc.styles['Normal']
        style.font.name = '微软雅黑'
        style._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')

        # 添加各个部分
        add_company_header(doc, company_data)
        add_company_overview(doc, company_data)
        add_business_analysis(doc, company_data)
        add_market_analysis(doc, company_data)
        add_competitive_analysis(doc, company_data)
        add_financial_analysis(doc, company_data)
        add_development_analysis(doc, company_data)
        add_risk_analysis(doc, company_data)
        add_corporate_structure(doc, company_data)
        add_management_info(doc, company_data)
        add_stock_analysis(doc, company_data)
        add_report_footer(doc)

        # 生成文件名并保存
        filename = f"{company_data['股票代码']}_{company_data['上市公司名称']}_详细分析报告.docx"
        filepath = os.path.join(output_dir, filename)
        doc.save(filepath)

        print(f"已生成报告：{filename}")
        return filepath

    except Exception as e:
        print(f"生成报告失败（{company_data['股票代码']}）: {str(e)}")
        return None


def batch_generate_reports(engine, limit=None):
    """批量生成所有公司报告"""
    # 读取数据
    df = read_company_detail_data(engine, limit)

    if df.empty:
        print("没有找到公司数据")
        return

    success_count = 0
    failed_companies = []

    for index, row in df.iterrows():
        print(f"正在生成 {row['股票代码']} {row['上市公司名称']} 的报告...")

        result = generate_company_report(row)
        if result:
            success_count += 1
        else:
            failed_companies.append(f"{row['股票代码']} {row['上市公司名称']}")

    # 输出统计信息
    print(f"\n报告生成完成！")
    print(f"成功生成：{success_count} 份")
    print(f"失败：{len(failed_companies)} 份")

    if failed_companies:
        print("失败的公司：")
        for company in failed_companies:
            print(f"  - {company}")


def generate_summary_report(engine, output_dir='company_reports'):
    """生成汇总报告"""
    try:
        df = read_company_detail_data(engine)

        doc = Document()

        # 标题
        title = doc.add_heading('', level=0)
        title_run = title.add_run('上市公司详细分析报告汇总')
        title_run.font.size = Pt(18)
        title_run.bold = True
        set_chinese_font(title_run)
        title.alignment = WD_ALIGN_PARAGRAPH.CENTER

        doc.add_paragraph()  # 空行

        # 统计信息
        p = doc.add_paragraph()
        p.add_run(f"报告生成时间：{datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')}\n")
        p.add_run(f"公司总数：{len(df)} 家\n")
        p.add_run(f"数据来源：company_detail_analysis表")

        # 公司列表表格
        doc.add_heading('公司列表', level=1)
        table = doc.add_table(rows=1, cols=5)
        table.style = 'Light Grid Accent 1'

        # 表头
        hdr_cells = table.rows[0].cells
        headers = ['代码', '名称', '一级行业', '二级行业', '上市时间']
        for i, header in enumerate(headers):
            hdr_cells[i].text = header
            for paragraph in hdr_cells[i].paragraphs:
                for run in paragraph.runs:
                    run.bold = True
                    set_chinese_font(run)

        # 数据行
        for _, row in df.iterrows():
            row_cells = table.add_row().cells
            row_cells[0].text = str(row['股票代码'])
            row_cells[1].text = str(row['上市公司名称'])
            row_cells[2].text = str(row['一级行业']) if pd.notna(row['一级行业']) and str(
                row['一级行业']) != '暂无信息' else '未知'
            row_cells[3].text = str(row['二级行业']) if pd.notna(row['二级行业']) and str(
                row['二级行业']) != '暂无信息' else '未知'
            row_cells[4].text = str(row['上市时间']) if pd.notna(row['上市时间']) and str(
                row['上市时间']) != '暂无信息' else '未知'

            for cell in row_cells:
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        set_chinese_font(run)

        # 保存汇总报告
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        summary_path = os.path.join(output_dir, '上市公司详细报告汇总.docx')
        doc.save(summary_path)
        print(f"汇总报告已生成：{summary_path}")

    except Exception as e:
        print(f"生成汇总报告失败: {str(e)}")


if __name__ == '__main__':
    try:
        # 创建数据库连接
        engine = create_database_connection()

        # 批量生成所有公司报告
        batch_generate_reports(engine)  # 先测试10家公司

        # 生成汇总报告
        # generate_summary_report(engine)

    except Exception as e:
        print(f"程序执行出错: {str(e)}")